// #include "mathvector2D.cpp"
#include <vector>
#include <list>
#include "ball.cpp"

using namespace std;

// 画布数据
const double WORLD_SIZE = 500;
// 环境数据
const int FOOD_NUM = 10;

list<Food> food_list;
list<FireBall> fireball_list;
list<SmartBall> sb_list;
int object_num = 0;

// 管理obs、reward、done
void updata()
{
    // cout<<"sb_list.size()"<<sb_list.size()<<endl;
    for (list<SmartBall>::iterator sb = sb_list.begin(); sb != sb_list.end();sb++)
    {

        sb->reward = 0;
        sb->obs.clear();

        // 吃food
        for (list<Food>::iterator food = food_list.begin(); food != food_list.end();)
        {
            MathVector relative_positoin = food->position - sb->position;
            if (norm(relative_positoin) <= food->radius + sb->radius)
            {
                // 发生碰撞
                // 领奖
                sb->hp += food->hp_add;
                food = food_list.erase(food);
                sb->reward+=food->hp_add;
            }
            else
            {

                vector<double> s = {relative_positoin.x, relative_positoin.y, food->radius, food->RGBA[0],
                                    food->RGBA[1], food->RGBA[2], food->RGBA[3], food->hp};
                sb->obs.push_back(s);
                food++;
            }
        }

        // 被fireball攻击
        for (list<FireBall>::iterator fireball = fireball_list.begin(); fireball != fireball_list.end();)
        {

            if (fireball->age == 0)
            {
                fireball = fireball_list.erase(fireball);
            }
            else
            {
                MathVector relative_positoin = fireball->position - sb->position;
                if ((norm(relative_positoin) <= fireball->radius + sb->radius) && (fireball->from_sb->id != sb->id))
                {
                    // 发生碰撞
                    // 伤害
                    sb->hp -= fireball->damage;
                    fireball->from_sb->reward+=fireball->damage;
                    
                }

                vector<double> s = {relative_positoin.x, relative_positoin.y, fireball->radius, fireball->RGBA[0],
                                    fireball->RGBA[1], fireball->RGBA[2], fireball->RGBA[3], fireball->hp};
                sb->obs.push_back(s);

                // cout<<fireball->age<<endl;
                fireball->age--;
                // cout<<fireball->age<<endl;
                fireball++;
            }
        }
        // 看见其他sb
        for (list<SmartBall>::iterator other_sb = sb_list.begin(); other_sb != sb_list.end();other_sb++)
        {
            MathVector relative_positoin = other_sb->position - sb->position;
            vector<double> s = {relative_positoin.x, relative_positoin.y, other_sb->radius, other_sb->RGBA[0],
                                other_sb->RGBA[1], other_sb->RGBA[2], other_sb->RGBA[3], other_sb->hp};
            sb->obs.push_back(s);
        }
    // cout<<1<<endl;
    }
    // cout << "3 ok" << endl;
}

// 重置环境，并输出初始状态
list<SmartBall> reset(int ran_seed, int sb_num)
{
    food_list.clear();
    fireball_list.clear();
    sb_list.clear();

    srand(ran_seed);

    for (int i = 0; i < sb_num; i++)
    {
        double x = rand() % int(WORLD_SIZE);
        double y = rand() % int(WORLD_SIZE);
        SmartBall sb = SmartBall(object_num, MathVector(x, y));
        object_num++;
        sb_list.push_back(sb);
    }

    for (int i = 0; i < FOOD_NUM; i++)
    {
        double x = rand() % int(WORLD_SIZE);
        double y = rand() % int(WORLD_SIZE);
        Food food = Food(object_num, MathVector(x, y));
        object_num++;
        food_list.push_back(food);
    }

    updata();
    return sb_list;
}

// 智能体真正执行动作。然后环境更新状态，并反馈一个奖励。
// done等于1意味着游戏结束；
// done等于0意味着游戏继续。
// 返回sb_list（包括done的sb）,然后在开头除去done的sb；所以python必须在sbdone时处理
list<SmartBall> step(vector<int> actions)
{
    // cout<<"succeed step!"<<endl;
    int i = 0;
    for (list<SmartBall>::iterator sb = sb_list.begin(); sb != sb_list.end();)
    {
        // TODO
        // if (sb->done)
        if (0)
        {
            sb_list.erase(sb);
        }
        else
        {
            if (actions[i] == 0)
            {
            }
            else if (actions[i] == 1)
            {
                sb->position.y -= sb->speed;
            }
            else if (actions[i] == 2)
            {
                sb->position.y += sb->speed;
            }
            else if (actions[i] == 3)
            {
                sb->position.x -= sb->speed;
            }
            else if (actions[i] == 4)
            {
                sb->position.x += sb->speed;
            }
            else if (actions[i] == 5)
            {
                FireBall fireball = FireBall(object_num, MathVector(sb->position.x, sb->position.y),
                                             sb->close_scope, sb->close_last, &*sb, sb->close_damage);
                object_num++;
                fireball_list.push_back(fireball);
            }
            else if (actions[i] == 6)
            {
                FireBall fireball = FireBall(object_num, MathVector(sb->position.x, sb->position.y),
                                             sb->far_scope, sb->far_last, &*sb, sb->far_damage);
                object_num++;
                fireball_list.push_back(fireball);
            }

            // 边界停止
            if (sb->position.x < 0)
            {
                sb->position.x += sb->speed;
            }
            if (sb->position.y < 0)
            {
                sb->position.y += sb->speed;
            }
            if (sb->position.x > WORLD_SIZE)
            {
                sb->position.x -= sb->speed;
            }
            if (sb->position.y > WORLD_SIZE)
            {
                sb->position.y -= sb->speed;
            }

            sb++;
            i++;
        }
    }

    // 补充foods
    for (int i = 0; i < FOOD_NUM - (int)food_list.size(); i++)
    {
        double x = rand() % int(WORLD_SIZE);
        double y = rand() % int(WORLD_SIZE);
        Food food = Food(object_num, MathVector(x, y));
        object_num++;
        food_list.push_back(food);
    }
    // 更新
    updata();


    // 判断死亡
    for (list<SmartBall>::iterator sb = sb_list.begin(); sb != sb_list.end();sb++)
    {
        if (sb->hp <= 0)
        {
            sb->done = 1;
        }
    }

    return sb_list;
}

// int main(int argc, char const *argv[])
// {
//     cout << FOOD_NUM << endl;
//     return 0;
// }
